#ifndef SMART_PTR_HPP_
#define SMART_PTR_HPP_

namespace lge2d
{

template <class T>
class SmartPtr
{
	struct Resource
	{
		unsigned usage;
		T* ptr;

		Resource() : usage(0), ptr(0) {}

		~Resource()
		{
			if (usage == 0 && ptr)
			{
				delete ptr;
				ptr = 0;
			}
		}
	};

public:

	SmartPtr(T* ptr = 0) : m_resource(0)
	{
		Init(ptr);
	}

	virtual ~SmartPtr()
	{
		Destroy();
	}

	void Reset(T* ptr = 0)
	{
		Destroy();
		Init(ptr);
	}

	SmartPtr(const SmartPtr& ptr)
	{
		m_resource = ptr.m_resource;
		if (m_resource)
		{
			m_resource->usage++;
		}
	}

	SmartPtr& operator = (const SmartPtr& ptr)
	{
		Destroy();

		m_resource = ptr.m_resource;
		if (m_resource)
		{
			m_resource->usage++;
		}

		return *this;
	}

	T* operator ->()
	{
		if (m_resource)
			return m_resource->ptr;
		return 0;
	}

	T* operator ->() const
	{
		if (m_resource)
			return m_resource->ptr;
		return 0;
	}

private:

	void Init(T* ptr)
	{
		if (ptr == 0)
			return;

		m_resource = new Resource();
		m_resource->usage = 1;
		m_resource->ptr = ptr;
	}

	void Destroy()
	{
		if (m_resource)
		{
			if (m_resource->usage > 0)
			{
				--m_resource->usage;
				if (m_resource->usage == 0)
				{
					delete m_resource;
				}
			}
			m_resource = 0;
		}
	}

private:

	Resource* m_resource;
};

} /* namespace lge2d */

#endif /* SMART_PTR_HPP_ */
